package com.ejlchina.tool.fragment.offline

import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.GridLayoutManager
import com.adolf.androiddemo.R
import com.adolf.androiddemo.databinding.FragmentConfigOfflineViewPagerBinding
import com.ejlchina.tool.MainActivity
import com.ejlchina.tool.adapter.ConfigWarningAdapter
import com.ejlchina.tool.base.BaseBindingFragment
import com.ejlchina.tool.bean.BleDeviceBean
import com.ejlchina.tool.bean.ConfigWarningBean
import com.ejlchina.tool.constant.COMMAND_DELAY_TIME_100
import com.ejlchina.tool.constant.OFFLINE_DEVICE_LEFT
import com.ejlchina.tool.constant.OFFLINE_DEVICE_RIGHT
import com.ejlchina.tool.enums.DoorStateEnum
import com.ejlchina.tool.enums.FanControlEnum
import com.ejlchina.tool.enums.SuccessFailEnum
import com.ejlchina.tool.util.COMMAND_AUTH_DOWNWARD
import com.ejlchina.tool.util.COMMAND_AUTH_UPWARD
import com.ejlchina.tool.util.COMMAND_DOOR_STATE_GET_DOWNWARD
import com.ejlchina.tool.util.COMMAND_DOOR_STATE_GET_OFFLINE_DOWNWARD
import com.ejlchina.tool.util.COMMAND_DOOR_STATE_GET_OFFLINE_UPWARD
import com.ejlchina.tool.util.COMMAND_DOOR_STATE_GET_UPWARD
import com.ejlchina.tool.util.COMMAND_DOOR_STATE_SET_DOWNWARD
import com.ejlchina.tool.util.COMMAND_DOOR_STATE_SET_OFFLINE_DOWNLOAD
import com.ejlchina.tool.util.COMMAND_DOOR_STATE_SET_OFFLINE_UPWARD
import com.ejlchina.tool.util.COMMAND_DOOR_STATE_SET_UPWARD
import com.ejlchina.tool.util.COMMAND_SWITCH_DOWNWARD
import com.ejlchina.tool.util.COMMAND_SWITCH_UPWARD
import com.ejlchina.tool.util.COMMAND_TEMPERATURE_ALARM_GET_DOWNWARD
import com.ejlchina.tool.util.COMMAND_TEMPERATURE_ALARM_GET_UPWARD
import com.ejlchina.tool.util.COMMAND_TEMPERATURE_ALARM_SET_DOWNLOAD
import com.ejlchina.tool.util.COMMAND_TEMPERATURE_ALARM_SET_UPWARD
import com.ejlchina.tool.util.COMMAND_TEMPERATURE_GET_OFFLINE_DOWNWARD
import com.ejlchina.tool.util.COMMAND_TEMPERATURE_GET_UPWARD_OFFLINE
import com.ejlchina.tool.util.LOG_TAG
import com.ejlchina.tool.util.bytearray.intTo32HexStringLE
import com.ejlchina.tool.util.bytearray.intToByteHexString
import com.ejlchina.tool.util.bytearray.readByteArrayLE
import com.ejlchina.tool.util.bytearray.toHexString
import com.ejlchina.tool.util.getBitValueFrom32Bits
import com.ejlchina.tool.util.setOnIntervalClickListener
import com.ejlchina.tool.util.showToast
import com.ejlchina.tool.view.GridItemDecoration
import com.ejlchina.tool.viewmodel.PRIORITY_WRITE_HIGH
import com.google.android.material.progressindicator.LinearProgressIndicator.IndeterminateAnimationType
import com.huyuhui.fastble.data.BleDevice
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.cancellable
import kotlinx.coroutines.launch


class ConfigOfflineViewPagerFragment(val bleDevice: BleDeviceBean):
    BaseBindingFragment<FragmentConfigOfflineViewPagerBinding>(FragmentConfigOfflineViewPagerBinding::inflate) {

    private val configWarningListLeft = arrayListOf<ConfigWarningBean>()
    private val configWarningListRight = arrayListOf<ConfigWarningBean>()
    private lateinit var configWarningAdapterLeft: ConfigWarningAdapter
    private lateinit var configWarningAdapterRight: ConfigWarningAdapter
    private var highWarningTemp = 0
    private var lowWarningTemp = 0
    private var fanControlMode = 1
    private var fanOpenTemp = 0
    private var mDoorStateEnumLeft = DoorStateEnum.CLOSE
    private var mDoorStateEnumRight = DoorStateEnum.CLOSE
    private var looperJob :Job? = null
    private var currentTemperatureLeft = 0
    private var currentTemperatureRight = 0
    private var isGetLeftTemperature = true
    private var isNeedSetFanState = true

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initViews()
    }

    private fun startLooperFlow(isNeedShowLoading: Boolean = true) {
        if (isNeedShowLoading){
            showLoading()
        }
        viewLifecycleOwner.lifecycleScope.launch {

            looperJob = launch {
                IntRange(1, Int.MAX_VALUE).asFlow().cancellable().collect{
                    getTemperature(true)
                    delay(COMMAND_DELAY_TIME_100)
                    getTemperature(false)
                    delay(COMMAND_DELAY_TIME_100)
                    getCommandData(bleDevice, COMMAND_SWITCH_DOWNWARD, "", false)
                    Log.i(LOG_TAG, "3=============================")
                    delay(COMMAND_DELAY_TIME_100)
                    getCommandData(bleDevice, COMMAND_TEMPERATURE_ALARM_GET_DOWNWARD, "", false)
                    Log.i(LOG_TAG, "4=============================")
                    delay(COMMAND_DELAY_TIME_100)
                    getCommandData(bleDevice, COMMAND_DOOR_STATE_GET_OFFLINE_DOWNWARD, intToByteHexString(OFFLINE_DEVICE_LEFT), false)
                    delay(COMMAND_DELAY_TIME_100)
                    getCommandData(bleDevice, COMMAND_DOOR_STATE_GET_OFFLINE_DOWNWARD, intToByteHexString(OFFLINE_DEVICE_RIGHT), false)
                    delay(900)
                }
            }
        }
    }

    private fun initViews(){
        initConfigWarningDataLeft()
        initConfigWarningDataRight()
        initMacAndVersion()
        initListeners()
    }
    private fun initListeners() {
        binding.includeSwitchFan.tvOn.setOnIntervalClickListener {
            handleFanClick(true)
        }

        binding.includeSwitchFan.tvOff.setOnIntervalClickListener {
            handleFanClick(false)
        }

        binding.btnOpenDoor1.setOnIntervalClickListener {
            viewLifecycleOwner.lifecycleScope.launch {
                handleDoorClick(OFFLINE_DEVICE_LEFT)
            }
        }

        binding.btnOpenDoor2.setOnIntervalClickListener {
            viewLifecycleOwner.lifecycleScope.launch {
                handleDoorClick(OFFLINE_DEVICE_RIGHT)
            }
        }
    }

    private fun handleFanClick(isFanOn: Boolean){
        isNeedSetFanState = false
        viewLifecycleOwner.lifecycleScope.launch {
            looperJob?.cancel()
            delay(500)
            setFanState(if (isFanOn) 2 else 0)
            setFanControlMode(if (isFanOn) FanControlEnum.ON else FanControlEnum.OFF)
            delay(700)
            startLooperFlow(false)
        }
    }

    private fun getTemperature(isLeft: Boolean){
        isGetLeftTemperature = isLeft
        val mode = (if (isLeft) OFFLINE_DEVICE_LEFT else OFFLINE_DEVICE_RIGHT)
        getCommandData(bleDevice, COMMAND_TEMPERATURE_GET_OFFLINE_DOWNWARD, intToByteHexString(mode), false)
    }

    private suspend fun handleDoorClick(index: Int){
        val operationView = if (index == OFFLINE_DEVICE_LEFT) binding.btnOpenDoor1 else binding.btnOpenDoor2
        val doorStateEnum = if (index == OFFLINE_DEVICE_LEFT) mDoorStateEnumLeft else mDoorStateEnumRight
        looperJob?.cancel()
        delay(500)
        setDoorControlData(index)
        when(doorStateEnum){
            DoorStateEnum.OPEN -> {
                operationView.text = DoorStateEnum.CLOSE_DOING.state
                operationView.setBackgroundResource(R.drawable.shape_co_11_so_bbc2f7)
            }
            DoorStateEnum.CLOSE -> {
                operationView.text = DoorStateEnum.OPEN_DOING.state
                operationView.setBackgroundResource(R.drawable.shape_co_11_so_bbc2f7)
            }
            else -> {}
        }
        delay(700)
        startLooperFlow(false)
    }


    private fun initMacAndVersion(){
        binding.tvMac.text = bleDevice.bleDevice.mac
        binding.tvVersion.text = bleDevice.version
    }
    private fun initConfigWarningDataLeft(){
        if (configWarningListLeft.isEmpty()){
            configWarningListLeft.apply {
                add(ConfigWarningBean(0,"温度(℃)")) //0
                add(ConfigWarningBean(1,"满溢")) //1
                add(ConfigWarningBean(2,"人体")) //2
                add(ConfigWarningBean(3,"按钮")) //3
            }
        }
        configWarningAdapterLeft = ConfigWarningAdapter(configWarningListLeft)
        binding.recycleView1.apply {
            adapter = configWarningAdapterLeft
            layoutManager = GridLayoutManager(requireContext(),3)
            if (itemDecorationCount == 0){
                addItemDecoration(GridItemDecoration(3,1,1))
            }
        }
    }

    private fun initConfigWarningDataRight(){
        if (configWarningListRight.isEmpty()){
            configWarningListRight.apply {
                add(ConfigWarningBean(0,"温度(℃)")) //0
                add(ConfigWarningBean(1,"满溢")) //1
                add(ConfigWarningBean(2,"人体")) //2
                add(ConfigWarningBean(3,"按钮")) //3
            }
        }
        configWarningAdapterRight = ConfigWarningAdapter(configWarningListRight)
        binding.recycleView2.apply {
            adapter = configWarningAdapterRight
            layoutManager = GridLayoutManager(requireContext(),3)
            if (itemDecorationCount == 0){
                addItemDecoration(GridItemDecoration(3,1,1))
            }
        }
    }

    private fun setDoorControlData(index: Int){
        val isOpenState = if (index == OFFLINE_DEVICE_LEFT) mDoorStateEnumLeft else mDoorStateEnumRight
        val commandData = intToByteHexString(index) + byteArrayOf(if (isOpenState == DoorStateEnum.CLOSE) 2.toByte() else 4.toByte()).toHexString(false)
        setCommandData(bleDevice, COMMAND_DOOR_STATE_SET_OFFLINE_DOWNLOAD, commandData, isNeedShowLoading = false)
    }

    private fun setFanState(dataByteArray: ByteArray){
        fanOpenTemp = dataByteArray[3].toInt()
        fanControlMode = dataByteArray[2].toInt()
        lowWarningTemp = dataByteArray[1].toInt()
        highWarningTemp = dataByteArray[0].toInt()

        when(fanControlMode){
            0 -> {
                setFanControlMode(FanControlEnum.OFF)
            }
            1 -> {
                val mode = if (fanOpenTemp > currentTemperatureLeft) FanControlEnum.OFF else FanControlEnum.ON
                setFanControlMode(mode)
            }
            2 -> {
                setFanControlMode(FanControlEnum.ON)
            }
        }
    }

    private fun setFanControlMode(controlMode: FanControlEnum){
        val resUnselected = R.drawable.shape_co_10_so_f7f7f7
        val resSelected = R.drawable.shape_co_10_so_1f39ff_2
        val selectedTextColor = resources.getColor(R.color.white)
        val unselectedTextColor = resources.getColor(R.color.title_text_color)
        binding.includeSwitchFan.tvOff.setBackgroundResource(resUnselected)
        binding.includeSwitchFan.tvOn.setBackgroundResource(resUnselected)
        binding.includeSwitchFan.tvOff.setTextColor(unselectedTextColor)
        binding.includeSwitchFan.tvOn.setTextColor(unselectedTextColor)
        when(controlMode){
            FanControlEnum.OFF -> {
                binding.includeSwitchFan.tvOff.setBackgroundResource(resSelected)
                binding.includeSwitchFan.tvOff.setTextColor(selectedTextColor)
            }

            FanControlEnum.ON -> {
                binding.includeSwitchFan.tvOn.setBackgroundResource(resSelected)
                binding.includeSwitchFan.tvOn.setTextColor(selectedTextColor)
            }
            else ->{}
        }
    }

    override fun whenReceiveCommand(bleDevice: BleDeviceBean, command: String, dataByteArray: ByteArray) {
        super.whenReceiveCommand(bleDevice,command, dataByteArray)
        if (bleDevice.bleDevice.mac != this@ConfigOfflineViewPagerFragment.bleDevice.bleDevice.mac) return
        when(command){
            COMMAND_TEMPERATURE_GET_UPWARD_OFFLINE -> {
                when(isGetLeftTemperature){
                    true -> currentTemperatureLeft = dataByteArray[dataByteArray.size - 1].toInt()
                    false -> currentTemperatureRight = dataByteArray[dataByteArray.size - 1].toInt()
                }
                refreshWarningData(dataByteArray[0].toInt(),0,dataByteArray[2].toInt().toString(),dataByteArray[1].toInt() == 0)

            }
            COMMAND_SWITCH_UPWARD -> {
                handleSwitchData(dataByteArray.readByteArrayLE(0,dataByteArray.size))
            }

            COMMAND_TEMPERATURE_ALARM_GET_UPWARD -> {
                (requireActivity() as MainActivity).saveData(1,this.bleDevice.bleDevice, COMMAND_TEMPERATURE_ALARM_SET_DOWNLOAD,dataByteArray.toHexString(false))
                if (isNeedSetFanState){
                    setFanState(dataByteArray)
                }else{
                    isNeedSetFanState = true
                }
            }

            COMMAND_TEMPERATURE_ALARM_SET_UPWARD -> {
                if (dataByteArray[dataByteArray.size - 1].toInt() == SuccessFailEnum.SUCCESS.value){
                    setFanState(dataByteArray)
                }
            }
            COMMAND_DOOR_STATE_GET_OFFLINE_UPWARD -> {
                setDoorStateUI(dataByteArray[0].toInt(),transformState(dataByteArray[1].toInt()))
                Log.i(LOG_TAG, dataByteArray[0].toInt().toString())
                dismissLoading() //以后可以改成第二个门的数据出来再消失
            }

            COMMAND_DOOR_STATE_SET_OFFLINE_UPWARD -> {
                if (dataByteArray[dataByteArray.size - 1].toInt() != SuccessFailEnum.SUCCESS.value){
                    showToast("设置失败")
                }
            }

            COMMAND_AUTH_UPWARD -> {

            }
        }
    }

    private fun transformState(value: Int): DoorStateEnum{
        return when(value) {
            1 -> DoorStateEnum.OPEN
            2 -> DoorStateEnum.OPEN_DOING
            3 -> DoorStateEnum.CLOSE
            else -> DoorStateEnum.CLOSE_DOING
        }
    }

    private fun handleSwitchData(dataByteArray: ByteArray){
        val isFullNormalLeft = getBitValueFrom32Bits(dataByteArray,0) == 0
        val isFullNormalRight = getBitValueFrom32Bits(dataByteArray,1) == 0
        val isBodyNormalLeft = getBitValueFrom32Bits(dataByteArray,2) == 0
        val isBodyNormalRight = getBitValueFrom32Bits(dataByteArray,3) == 0
        val isButtonNormalLeft = getBitValueFrom32Bits(dataByteArray,4) == 0
        val isButtonNormalRight = getBitValueFrom32Bits(dataByteArray,5) == 0

        val fullValueLeft = if (isFullNormalLeft) "正常" else "溢出"
        val fullValueRight = if (isFullNormalRight) "正常" else "溢出"
        val bodyValueLeft = if (isBodyNormalLeft) "无人" else "有人"
        val bodyValueRight = if (isBodyNormalRight) "无人" else "有人"
        val buttonValueLeft = if (isButtonNormalLeft) "释放" else "按下"
        val buttonValueRight = if (isButtonNormalRight) "释放" else "按下"

        refreshWarningData(OFFLINE_DEVICE_LEFT,1,fullValueLeft,isFullNormalLeft)
        refreshWarningData(OFFLINE_DEVICE_RIGHT,1,fullValueRight,isFullNormalRight)
        refreshWarningData(OFFLINE_DEVICE_LEFT,2,bodyValueLeft,isBodyNormalLeft)
        refreshWarningData(OFFLINE_DEVICE_RIGHT,2,bodyValueRight,isBodyNormalRight)
        refreshWarningData(OFFLINE_DEVICE_LEFT,3,buttonValueLeft,isButtonNormalLeft)
        refreshWarningData(OFFLINE_DEVICE_RIGHT,3,buttonValueRight,isButtonNormalRight)
    }

    private fun refreshWarningData(deviceIndex: Int, index: Int, value: String, isNormal: Boolean){
        val configList = if (deviceIndex == OFFLINE_DEVICE_LEFT) configWarningListLeft else configWarningListRight
        val adapter = if (deviceIndex == OFFLINE_DEVICE_LEFT) configWarningAdapterLeft else configWarningAdapterRight
        configList[index].value = value
        configList[index].isNormal = isNormal
        adapter.notifyItemChanged(index,null)
    }

    private fun setDoorStateUI(deviceIndex: Int,doorStateEnum: DoorStateEnum){
        val operationView: View
        if (deviceIndex == OFFLINE_DEVICE_LEFT){
            operationView = binding.btnOpenDoor1
            mDoorStateEnumLeft = doorStateEnum
        } else {
            mDoorStateEnumRight = doorStateEnum
            operationView = binding.btnOpenDoor2
        }

        lifecycleScope.launch {
            when(doorStateEnum){
                DoorStateEnum.OPEN -> {
                    operationView.apply {
                        setBackgroundResource(R.drawable.shape_co_11_so_1f39ff)
                        text = doorStateEnum.state
                        isEnabled = true
                    }
                }
                DoorStateEnum.OPEN_DOING -> {
                    operationView.apply {
                        setBackgroundResource(R.drawable.shape_co_11_so_bbc2f7)
                        text = doorStateEnum.state
                        isEnabled = false
                    }
                }

                DoorStateEnum.CLOSE -> {
                    operationView.apply {
                        setBackgroundResource(R.drawable.shape_co_11_so_1f39ff)
                        text = doorStateEnum.state
                        isEnabled = true
                    }
                }

                DoorStateEnum.CLOSE_DOING -> {
                    operationView.apply {
                        setBackgroundResource(R.drawable.shape_co_11_so_bbc2f7)
                        text = doorStateEnum.state
                        isEnabled = false
                    }
                }
            }
        }
    }

    private fun setFanState(fanState: Int){
        val byteArray = byteArrayOf(highWarningTemp.toByte(),lowWarningTemp.toByte(),fanState.toByte(),fanOpenTemp.toByte())
        setCommandData(bleDevice, COMMAND_TEMPERATURE_ALARM_SET_DOWNLOAD,byteArray.toHexString(false), isNeedShowLoading = false, priority = PRIORITY_WRITE_HIGH)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        looperJob?.cancel()
        (requireActivity() as MainActivity).restoreData(1)
        Log.i(LOG_TAG,"Ondestory View")
    }

    override fun onPause() {
        super.onPause()
        looperJob?.cancel()
        Log.i(LOG_TAG,"offline pause")
    }

    override fun onResume() {
        super.onResume()
        startLooperFlow(true)
    }
}